package com.zen.lon.open.remote.support;

import com.zen.lon.open.remote.annotation.EnableRemoteClient;
import com.zen.lon.open.remote.annotation.RemoteClient;
import com.zen.lon.open.remote.utils.ClassProviderUtils;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.util.StringUtils;

/**
 * RemoteApi扫描器 优先扫描注解添加的扫描器，如果没有则默认应用启动类目录下实现进行扫描
 *
 * @author ZonLen since on 2021/7/1 下午12:03
 */
public class RemoteClientScanner extends ClassPathBeanDefinitionScanner {


  RemoteClientScanner(BeanDefinitionRegistry registry) {
    super(registry, false);
    addIncludeFilter(new AnnotationTypeFilter(RemoteClient.class, true, true));
  }

  /**
   * 判断是否是候选的bean
   */
  @Override
  public boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
    final AnnotationMetadata metadata = beanDefinition.getMetadata();
    return metadata.isInterface() && metadata.isIndependent() && metadata
        .hasAnnotation(RemoteClient.class.getName());
  }

  /**
   * 获取扫描包路径
   */
  Set<String> getBasePackages(AnnotationMetadata annotationMetadata) {
    Map<String, Object> attributes = annotationMetadata
        .getAnnotationAttributes(EnableRemoteClient.class.getCanonicalName());
    Set<String> basePackages = new HashSet<>();
    for (String pkg : (String[]) MapUtils.emptyIfNull(attributes).get("basePackages")) {
      pkg = ApplicationContextProvider.resolvePlaceholders(pkg);
      if (StringUtils.hasText(pkg)) {
        basePackages
            .addAll(Arrays.asList(pkg.split(",")));
      }
    }
    if (basePackages.isEmpty()) {
      basePackages.add(ClassProviderUtils.deduceMainApplicationClass());
    }
    return basePackages;
  }

}
